<?php

/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

require_once ('api/IRouter.php');

/**
 *
 *
 * @author Rodrigo Rutkoski Rodrigues <rutkoski@gmail.com>
 * @package Simplify_Kernel_Core
 */
class AutoRouterImpl implements IRouter
{

  /**
   *
   * @var array
   */
  protected $parsed = array();

  /**
   *
   * @var ICache
   */
  protected $cache;

  /**
   *
   * @var string
   */
  protected $cacheid = 'router';

  public function initialize()
  {
  }

  /**
   *
   * @return ICache
   */
  protected function getCache()
  {
    static $cache;

    if (empty($cache)) {
      $cache = new YAMLFileCache();

      if ($cache->cached($this->cacheid)) {
        $this->cache = $cache->read($this->cacheid);

        if (! is_array($this->cache)) {
          $this->cache = array();
        }
      }
    }

    if (Simplify::getRequest()->get()->has('CLEAR_AUTO_ROUTER_CACHE')) {
      $cache->write($this->cacheid, array());
      $this->cache = array();
    }

    return $cache;
  }

  protected function cache($route, $data)
  {
    $cache = $this->getCache();
    $this->cache[$route] = $data;
    $cache->write($this->cacheid, $this->cache);
  }

  public function build($route, $params)
  {
  }

  public function parse($route)
  {
    $this->getCache();

    if (! isset($this->cache[$route])) {
      try {
        $home = Simplify::getConfig()->get('home_dir', '{app_dir}/home');
        $data = $this->find($route, $home);
        $this->cache($route, $data);
      }
      catch (RouterException $e) {
        $home = Simplify::getConfig()->get('sy_dir') . '/app/home';
        $data = $this->find($route, $home);
      }

      $data = Dictionary::parseFrom($data);
    }
    else {
      $data = Dictionary::parseFrom($this->cache[$route]);

      $file = $data->get('path') . '/' . $data->get('controller') . '_controller.php';

      if (! file_exists($file)) {
        throw new RouterException("Controller file not found: <b>$file</b>");
      }

      require_once ($file);
    }

    return $data;
  }

  protected function find($route, $home)
  {
    $words = array_values(array_filter(explode('/', $route)));

    $path = array();
    $dir = null;
    while (count($words) && is_dir($home . '/' . implode('/', $path) . '/' . $words[0])) {
      $path[] = $dir = array_shift($words);
    }

    if (empty($dir)) {
      $dir = Simplify::getConfig()->get('home_controller', 'home');
    }

    $path = $home . '/' . implode('/', $path);

    if (count($words) && file_exists($path . '/' . $words[0] . '_controller.php')) {
      $controller = array_shift($words);
    }
    elseif (file_exists($path . '/' . $dir . '_controller.php')) {
      $controller = $dir;
    }

    if (empty($controller)) {
      throw new RouterException("Path found but controller not found in route: <b>$route</b>");
    }

    require_once ($path . '/' . $controller . '_controller.php');

    $action = 'index';
    if (count($words) && Simplify::getInstance()->controllerActionExists($controller, $words[0], array_slice($words, 1))) {
      $action = array_shift($words);
    }

    $data = array();
    $data['path'] = $path;
    $data['controller'] = $controller;
    $data['action'] = $action;
    $data['params'] = $words;

    return $data;
  }

}

?>